<!--文件上传组件-->
<template>
	<div class="upload-file">
		<el-upload
			ref="fileUpload"
			:action="baseURL + other.adaptationUrl(props.uploadFileUrl)"
			:before-upload="handleBeforeUpload"
			:file-list="fileList"
			:headers="headers"
			:limit="limit"
			:on-error="handleUploadError"
			:on-remove="handleRemove"
			:on-preview="handlePreview"
			:data="formData"
			:auto-upload="autoUpload"
			:on-success="handleUploadSuccess"
			class="upload-file-uploader"
			drag
		>
			<i class="el-icon-upload"></i>
			<div class="el-upload__text">
				{{ $t('excel.operationNotice') }}
				<em>{{ $t('excel.clickUpload') }}</em>
			</div>
			<template #tip>
				<div class="el-upload__tip" v-if="props.isShowTip">
					{{ $t('excel.pleaseUpload') }}
					<template v-if="props.fileType">
						{{ $t('excel.format') }} <b style="color: #f56c6c">{{ props.fileType.join('/') }}</b>
					</template>
					{{ $t('excel.file') }}
				</div>
			</template>
		</el-upload>
	</div>
</template>

<script setup lang="ts" name="upload-file">
import { useMessage } from '@/hooks/message';
import { Session } from '@/utils/storage';
import other from '@/utils/other';
import { useI18n } from 'vue-i18n';
import { IFileVO } from '@/api/admin/file.type';
import { delObj } from '@/api/admin/file';
import { UploadFile } from 'element-plus';
import { IProjectFileDTO } from '@/api/oa/project.type';

const props = defineProps({
	modelValue: {
		type: Array<IProjectFileDTO>,
		default: () => [],
	},
	// 数量限制
	limit: {
		type: Number,
		default: 5,
	},
	fileType: {
		type: Array,
		default: () => ['png', 'jpg', 'jpeg', 'doc', 'xls', 'ppt', 'txt', 'pdf', 'docx', 'xlsx', 'pptx', 'zip', 'rar', '7z'],
	},
	// 是否显示提示
	isShowTip: {
		type: Boolean,
		default: true,
	},
	uploadFileUrl: {
		type: String,
		default: '/admin/sys-file/upload',
	},
	data: {
		type: Object,
		default: () => ({}),
	},
	dir: {
		type: String,
		default: '',
	},
	autoUpload: {
		type: Boolean,
		default: true,
	},
});

const emit = defineEmits(['update:modelValue', 'change']);

const fileList = ref<UploadFile[]>([]);
const fileUpload = ref();
const { t } = useI18n();

// 请求头处理
const headers = computed(() => {
	return {
		Authorization: 'Bearer ' + Session.get('token'),
		'TENANT-ID': Session.getTenant(),
	};
});

// 请求参数处理
const formData = computed(() => {
	return Object.assign(props.data, { dir: props.dir });
});

// 上传前校检格式和大小
const handleBeforeUpload = (file: File) => {
	// 校检文件类型
	if (props.fileType.length) {
		const fileName = file.name.split('.');
		const fileExt = fileName[fileName.length - 1];
		const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
		if (!isTypeOk) {
			useMessage().error(`${t('excel.typeErrorText')} ${props.fileType.join('/')}!`);
			return false;
		}
	}
	return true;
};

// 上传成功回调
function handleUploadSuccess(res: IResWrapper<IFileVO>, file: UploadFile) {
	if (res.code === 0) {
		const { fileId, bucketName, fileName, originalFilename, url } = res.data;
		const arr = [
			...props.modelValue,
			{
				id: fileId,
				original: originalFilename,
				fileName,
				bucketName,
				url,
			},
		];
		emit('update:modelValue', arr);
	} else {
		useMessage().error(res.msg || '上传失败，请重试');
		fileUpload.value.handleRemove(file);
	}
}

const handleRemove = async (file: UploadFile & { id: string }) => {
	await delObj([file.id]);
	useMessage().success('删除成功');
	const arr = [...props.modelValue];
	const index = arr.findIndex((item) => item.id === file.id);
	arr.splice(index, 1);
	emit('update:modelValue', arr);
};

const handlePreview = (file: UploadFile) => {
	other.downBlobFile(file.url, {}, file.name);
};

const handleUploadError = () => {
	useMessage().error('上传文件失败');
};

/**
 * 监听 props 中的 modelValue 值变化，更新 fileList。
 */
watch(
	() => props.modelValue,
	(val) => {
		if (val) {
			fileList.value = val.map((item) => ({
				uid: +item.id,
				name: item.original,
				status: 'success',
				url: item.url,
				id: item.id,
			}));
		} else {
			fileList.value = [];
		}
	},
	{ deep: true, immediate: true }
);

const submit = () => {
	fileUpload.value.submit();
};

defineExpose({
	submit,
});
</script>
